#include "hpcr_types.h"
#include "core/hpcr_list.h"

hpcr_list_t *hpcr_list_init(hpcr_list_t *list)
{
    list->head.pre = NUL;
    list->head.next = &list->tail;
    list->tail.pre = &list->head;
    list->tail.next = NUL;
    return list;
}

{
    hpcr_list_node_t *tmp = dst->next;
    dst->next = node;
    tmp->pre = node;
    node->pre = dst;
    node->next = tmp;
}

void hpcr_list_insert_before(hpcr_list_node_t *dst, hpcr_list_node_t *node)
{
    hpcr_list_node_t *tmp = dst->pre;
    dst->pre = node;
    tmp->next = node;
    node->pre = tmp;
    node->next = dst;
}

// 头插
void hpcr_list_push(hpcr_list_t *list, hpcr_list_node_t *node)
{
    hpcr_list_insert_after(&list->head, node);
}

// 尾插
void hpcr_list_append(hpcr_list_t *list, hpcr_list_node_t *node)
{
    hpcr_list_insert_after(list->tail.pre, node);
}

// 移除
bool hpcr_list_remove(hpcr_list_node_t *node)
{
    if (node->next == NUL || node->pre == NUL)
    {
        return false;
    }

    node->pre->next = node->next;
    node->next->pre = node->pre;
    node->pre = NUL;
    node->next = NUL;
}

// pop
hpcr_list_node_t *hpcr_list_pop(hpcr_list_t *list)
{
    hpcr_list_node_t *node = list->head.next;
    if (node->next == NUL || node->pre == NUL)
    {
        return NUL;
    }

    node->pre->next = node->next;
    node->next->pre = node->pre;
    node->pre = NUL;
    node->next = NUL;
    return node;
}

// 顺序插入
void hpcr_list_insert_order(hpcr_list_t *list, hpcr_list_node_t *node, hpcr_list_node_compare_handle compare)
{
    hpcr_list_node_t *tmp = list->head.next;
    while (tmp->next != NUL)
    {
        if (!compare(tmp, node))
        {
            break;
        }
        tmp = tmp->next;
    }
    hpcr_list_insert_before(tmp, node);
}

// 查找
hpcr_list_node_t *hpcr_list_find(hpcr_list_t *list, hpcr_list_node_search_handle search, void *arg)
{
    hpcr_list_node_t *tmp = list->head.next;
    while (tmp->next != NUL)
    {
        if (search(tmp, arg))
        {
            return tmp;
        }
        tmp = tmp->next;
    }
    return NUL;
}

// 判断列表是否为空
bool hpcr_list_empty(hpcr_list_t *list)
{
    return list->head.next == &list->tail;
}

// 返回列表大小
hpcr_size_t hpcr_list_size(hpcr_list_t *list)
{
    hpcr_size_t size = 0;
    hpcr_list_node_t *tmp = list->head.next;
    while (tmp->next != NUL)
    {
        size += 1;
        tmp = tmp->next;
    }
    return size;
}
